package advance.juc.executor;

import java.util.concurrent.*;

/**
 * 统一线程池创建工厂，并通过 ThreadPoolManager 主动创建爱你线程池资源，
 * 实现线程统一生命周期管理{@link ExecutorFactory.Managed}
 */
public final class ExecutorFactory {

    /**
     * 创建固定线程池大小
     * 注意：线程等待队列最大为 Integer.MAX_VALUE
     * @return
     */
    public static ExecutorService newSingleExecutorService() {
        return Executors.newFixedThreadPool(1);
    }

    /**
     * 根据自定义线程工厂创建固定线程池大小
     * 注意：线程等待队列最大为 Integer.MAX_VALUE
     * @param threadFactory
     * @return
     */
    public static ExecutorService newSingleExecutorService(final ThreadFactory threadFactory) {
        return Executors.newFixedThreadPool(1, threadFactory);
    }

    /**
     * 创建固定线程池大小
     * 注意：线程等待队列最大为 Integer.MAX_VALUE
     * @param nThreads
     * @return
     */
    public static ExecutorService newFixedExecutorService(final int nThreads) {
        return Executors.newFixedThreadPool(nThreads);
    }

    /**
     * 创建固定线程池大小
     * 注意：线程等待队列最大为 Integer.MAX_VALUE
     * @param nThreads
     * @param threadFactory
     * @return
     */
    public static ExecutorService newFixExecutorService(final int nThreads, final ThreadFactory threadFactory) {
        return Executors.newFixedThreadPool(nThreads, threadFactory);
    }

    public static ScheduledExecutorService newSingleScheduledExecutorService(final ThreadFactory threadFactory) {
        return Executors.newScheduledThreadPool(1, threadFactory);
    }

    public static ScheduledExecutorService newScheduledExecutorService(final int nThread, final ThreadFactory threadFactory) {
        return Executors.newScheduledThreadPool(nThread, threadFactory);
    }

    public static ThreadPoolExecutor newCustomerThreadExecutor(final int coreThreads,
                                                               final int maxThreads,
                                                               final long keepAliveTimeMs,
                                                               final ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(coreThreads,
                maxThreads,
                keepAliveTimeMs,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), threadFactory);
    }

    public static final class Managed {
        private static final String DEFAULT_NAMESPACE = "nacos";

        private static final ThreadPoolManager THREAD_POOL_MANAGER = ThreadPoolManager.getInstance();

        public static ExecutorService newSingleExecutorService(final String group) {
            ExecutorService executorService = Executors.newFixedThreadPool(1);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
            return executorService;
        }

        public static ExecutorService newSingleExecutorService(final String group, final ThreadFactory threadFactory) {
            ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
            return executorService;
        }

        public static ExecutorService newFixedExecutorService(final String group, final int nThreads) {
            ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
            return executorService;
        }

        public static ExecutorService newFixedExecutorService(final String group, final int nThread, final ThreadFactory threadFactory) {
            ExecutorService executorService = Executors.newFixedThreadPool(nThread, threadFactory);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
            return executorService;
        }

        public static ScheduledExecutorService newSingleScheduledExecutorService(final String group,
                                                                                 final ThreadFactory threadFactory) {
            ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, threadFactory);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
            return executorService;
        }

        public static ScheduledExecutorService newScheduledExecutorService(final String group, final int nThreads,
                                                                           final ThreadFactory threadFactory) {
            ScheduledExecutorService executorService = Executors.newScheduledThreadPool(nThreads, threadFactory);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
            return executorService;
        }

        public static ThreadPoolExecutor newCustomerThreadExecutor(final String group, final int coreThreads,
                                                                   final int maxThreads, final long keepAliveTimeMs, final ThreadFactory threadFactory) {
            ThreadPoolExecutor executor = new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs,
                    TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executor);
            return executor;
        }
    }
}
